import {BitConverter,MingArray,CrcUtils,Convert} from "./DdaReaderUtils.js";


class NPack {
  _v=[];
  static  EmptyPack(type, len){
    let np=new NPack();
    np._v[0] = (len & 0xff);
    np._v[1] = (len >>8 & 0xff);
    np._v[2] = (type & 0xff);
    np._v[3] = (type >> 8 & 0xff);
    return np;
  }

  static  Pack(){
    return NPack.EmptyPack(DdaReader.PACK_TYPE, 4);
  }

  GetMember( index){
    if(this.DataType()!= DdaReader.PACK_TYPE)
    {
      return this;
    }
    let totalLength = (BitConverter.ToInt16( this._v, 0));
    let sumLength = 4;
    let memberPtrInx = 4;
    let count = 0;
    while (sumLength < totalLength)
    {
      if(count< index)
      {
        let memberLength = (ushort)(BitConverter.ToInt16(this._v, memberPtrInx));
        sumLength += memberLength;
        memberPtrInx += memberLength;
        count++;
      }
      else
      {
        break;
      }
    }
    let memberPack = NPack.Pack();
    MingArray.Copy(this._v, memberPtrInx, memberPack._v, 0, this._v[memberPtrInx]);
    return memberPack;
  }

  Count()
  {
    let totalLength = (BitConverter.ToInt16(this._v, 0));
    let sumLength = 4;
    let memberPtrInx = 4;
    let  count = 0;
    if (this.DataType()== DdaReader.NA_TYPE)
    {
      return 0;
    }
    if (this.DataType() !=DdaReader.PACK_TYPE)
    {
      return 1;
    }
    else
    {
      while (sumLength < totalLength)
      {
        let memberLength = (BitConverter.ToInt16(this._v, memberPtrInx));
        sumLength += memberLength;
        memberPtrInx += memberLength;
        count++;
      }
    }
    return (count);
  }

  AppendWord( v) { return this.AppendPack(NPack.Word(v));}


  AppendPack( v)
  {
    if (this.DataType()== DdaReader.PACK_TYPE)
    {
      MingArray.Copy(v._v, 0, this._v, this.Length(), v.Length());
      let len =this.Length() + v.Length();
      this._v[0] = (len & 0xff);
      this._v[1] = (len >> 8 & 0xff);
    }
    return this;
  }

  static Word(v)
  {
    let np= NPack.EmptyPack(DdaReader.W_TYPE,6);
    let bs = BitConverter.GetBytes(v);
    MingArray.Copy(bs,0, np._v, 4,2);
    return np;
  }


  ToWord()
  {
    return BitConverter.ToInt16(this._v, 4);
  }

  static DWord(v)
  {
    let np= NPack.EmptyPack(DdaReader.DW_TYPE,8);
    let bs = BitConverter.GetBytes(v);
    MingArray.Copy(bs,0, np._v, 4,4);
    return np;
  }


  ToDWord()
  {
    return BitConverter.ToInt32(this._v, 4);
  }


  static  Str(v)
  {
    let bs=[];
    let np= NPack.EmptyPack(DdaReader.STR_TYPE,20);
    for (let i=0;i<16;i++){
      let vi=v.charCodeAt(i);
      if(!vi){
        bs.push(0)
      }else {
        bs.push(vi)
      }
    }
    MingArray.Copy(bs,0,np._v,4,16);
    np._v[4+bs.Length] = 0;
    return np;
  }


  ToStr()
  {
    let strBuf=[];
    for (let j=0;j<16;j++){
      strBuf[j]=this._v[4+j];
      if(strBuf[j]==0){
        break;
      }
    }
    return String.fromCharCode.apply(String, strBuf);
  }


  DataType()
  {
    return (BitConverter.ToInt16(this._v, 2));
  }

  Length()
  {
    return BitConverter.ToInt16(this._v, 0);
  }

  DataBody(){
    return this._v;
  }

  IsEmpty()
  {
    return this.DataType() ==DdaReader.NA_TYPE;
  }
  ToString( format=0)
  {
    let retStr="NULL";
    if (this._v == null)
    {
      return retStr;
    }
    switch (this.DataType())
    {
      case DdaReader.W_TYPE:
      {
        if (format == 0)
        {
          retStr = Convert.ToString(this.ToWord());
        }else if (format == 16)
        {
          retStr = Convert.ToString(this.ToWord(),16);
        }
        break;
      }
      case DdaReader.DW_TYPE:
      {
        if (format == 0)
        {
          retStr = Convert.ToString(this.ToDWord());
        }
        else if (format == 16)
        {
          retStr = Convert.ToString(this.ToDWord(), 16);
        }
        break;
      }
      case DdaReader.STR_TYPE:
      {
        retStr = this.ToStr();
        break;
      }
      case DdaReader.PACK_TYPE:
      {
        let cnt = this.Count();
        retStr = "";
        for (let i = 0; i < cnt; i++)
        {
          retStr = retStr + this.GetMember(i).ToString(format);
          if (i < cnt - 1)
          {
            retStr = retStr + ",";
          }
        }
        break;
      }


    }
    return retStr;
  }

}
class DdaReader{

  static  CALL_Echo    =       0x98A4   ;
  static  CALL_Connect  =      0xB5AF   ;
  static  CALL_Disconnect =    0x16EF   ;
  static  CALL_GetDdaVer  =    0x6F5B   ;
  static  CALL_GetEntryNum=    0x0687   ;
  static  CALL_GetEntry    =   0x9E97    ;
  static  CALL_SetParam  =     0x7B02   ;
  static  CALL_GetParam  =     0x8076   ;
  static  EVENT_ParamChanged = 0x7C60   ;
  static  CALL_SetRefExt =     0x84BF   ;
  static  CALL_SetRefGen =     0x8AC8    ;
  static  CALL_CtrlStop =      0x7620    ;
  static  CALL_CtrlOpen =      0x324C    ;
  static  CALL_CtrlMotion =    0xBEB0    ;
  static  CALL_CtrlClosed =    0x4A34    ;

  static  NA_TYPE       =  0x0000   ;       // 无效类型
  static  W_TYPE        =  0x0001   ;       // 字
  static  DW_TYPE       =  0x0002   ;       // 双字
  static  STR_TYPE      =  0x0010   ;       // 字符串
  static  WA_TYPE       =  0x0011   ;       // 字数组
  static  DWA_TYPE      =  0x0012   ;       // 双字数组
  static  STRUCT_TYPE	=	0x0020  ;        // 结构
  static  STRUCT_A_TYPE =  0x0021	;		// 结构数组
  static  LIST_TYPE     = 0x0040    ;      // 同类成员列
  static  PACK_TYPE = 0x0080;		// 异类成员包

  static send=async function (v){
     return v;
  }

  static GetParam= async (instanceId, memId)=>
  {
      let reqNPack = NPack.Pack().AppendWord(memId);
      let resNPack =await DdaReader.Rpc(DdaReader.CALL_GetParam, instanceId,  reqNPack);
      return resNPack;
  }

  static SetParam=async ( instanceId,  memId, nPack)=>
  {
     let reqNPack = NPack.Pack().AppendWord(memId).AppendPack(nPack);
     let resNPack =await DdaReader.Rpc(DdaReader.CALL_SetParam, instanceId,  reqNPack);
     return resNPack;
  }




static Rpc= async (  callId,  ddaId,   reqNpack)=>
   {
      let m_bBuffer=[];
      m_bBuffer[0]=0xf7;
      m_bBuffer[1] = 0x64;
      m_bBuffer[2] =  (callId >> 8 & 0xff);
      m_bBuffer[3] =(callId & 0xff);
      m_bBuffer[4] = (ddaId >> 8 & 0xff);
      m_bBuffer[5] = (ddaId & 0xff);
     for (let i=0;i<reqNpack._v[0];i++){
       m_bBuffer[6+i]=reqNpack._v[i]
     }
     let [hi,lo]= CrcUtils.CRC16(m_bBuffer);
     m_bBuffer.push(hi);
     m_bBuffer.push(lo);
     //let dd=  m_bBuffer.map(u=>u.toString(16).padStart(2,0))
    // console.log(dd)
     let r=await  DdaReader.send(m_bBuffer);
     if(r && r.length>8){
       let np= NPack.Pack();
       for (let i=0;i<r[6];i++){
          np._v[i]=r[6+i]
       }
       return np;
     }
      return 0;
  }




}

export  {DdaReader,NPack};